package cn.walls1717.wallsmall.seckill.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * RabbitMQ配置类
 *
 * @author walls1717
 * @since 2022/11/17 15:51
 **/
@Configuration
@Slf4j
public class RabbitConfig {
    @Resource
    private RabbitTemplate rabbitTemplate;



    /**
     * 使用Json序列化工具，对消息序列化。<br>
     * 默认使用的是JDK序列化工具
     *
     * @return MessageConverter
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 在RabbitConfig对象创建完成之后，执行此方法。<br>
     * RabbitTemplate初始化
     */
    @PostConstruct
    public void initRabbitTemplate() {
        // 设置消息成功发送回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             * 确认方法<br>
             * 只要消息抵达broker，ack就为true。
             *
             *
             * @param correlationData 当前消息的唯一关联数据(消息唯一id)
             * @param ack 消息是否成功收到
             * @param cause 失败原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                log.info("confirm -> {\"correlationData\":\"{}\",\"ack\":\"{}\",\"cause\":\"{}\"}", correlationData,
                    ack, cause);
            }
        });

        // 设置消息抵达队列回调
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            /**
             * 消息没有投递给指定的队列，触发此失败回调。
             *
             * @param message 失败消息的详情
             * @param replyCode 回复状态码
             * @param replyText 回复消息
             * @param exchange 消息发动的交换机
             * @param routingKey 消息的路由键
             */
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange,
                String routingKey) {

                log.info("message -> {}", message);
                log.info(
                    "badReturn -> {\"replyCode\":\"{}\",\"replyText\":\"{}\",\"exchange\":\"{}\",\"routingKey\":\"{}\"}",
                    replyCode, replyText, exchange, routingKey);
            }
        });
    }
}
